package cn.ztydata.teachingsystem.heaven.dao.redis;

import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Repository;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 习题->知识点 redis类
 * Created by chenxin on 2015/02/04.
 */
@Repository
public class ExerciseKpDao extends BaseRedisDao {
    private static final String EXERCISE_KP = "exercise_kp";
    static final String KP_EXERCISE = "kp_exercise";

    /**
     * 保存习题与知识点的关系
     * @param exerciseId 习题ID
     * @param kpId 知识点ID
     * @return Boolean
     *
     * @author cx
     * @since 2015-02-04
     */
    public Boolean saveKp(final long exerciseId, final long kpId) {
        SessionCallback<Boolean> sessionCallback = new SessionCallback<Boolean>() {
            @Override
            public Boolean execute(RedisOperations operations) throws DataAccessException {
                operations.multi();

                //获取List操作
                ListOperations<String, Long> listOperations = operations.opsForList();
                //获取Set操作
                SetOperations<String, Long> setOperations = operations.opsForSet();

                //保存习题->知识点的关系
                listOperations.rightPush(KeyUtils.generateKey(EXERCISE_KP, exerciseId), kpId);
                //保存知识点->习题的关系
                setOperations.add(KeyUtils.generateKey(KP_EXERCISE, kpId), exerciseId);

                operations.exec();
                return true;
            }
        };

        logger.debug("保存习题与知识点关系成功");
        return (Boolean)redisTemplate.execute(sessionCallback);
    }

    /**
     * 删除习题与知识点的关系
     * @param exerciseId 习题ID
     * @param kpId 知识点ID
     * @return Boolean
     *
     * @author cx
     * @since 2015-02-04
     */
    public Boolean deleteKp(final long exerciseId, final long kpId) {
        SessionCallback<Boolean> sessionCallback = new SessionCallback<Boolean>() {
            @Override
            public Boolean execute(RedisOperations operations) throws DataAccessException {
                operations.multi();
                //获取List操作
                ListOperations<String, Long> listOperations = operations.opsForList();
                //获取Set操作
                SetOperations<String, Long> setOperations = operations.opsForSet();

                //删除习题->知识点的关系
                listOperations.remove(KeyUtils.generateKey(EXERCISE_KP, exerciseId), 0, kpId);
                //删除知识点->习题的关系
                setOperations.remove(KeyUtils.generateKey(KP_EXERCISE, kpId), exerciseId);

                operations.exec();
                return true;
            }
        };

        return (Boolean)redisTemplate.execute(sessionCallback);
    }

    /**
     * 获取习题的所有知识点ID集合
     * @param exerciseId 知识点ID
     * @return List
     *
     * @author cx
     * @since 2015-02-04
     */
    public List<Long> getKpIds(final long exerciseId) {
        //获取List操作
        ListOperations<String, Long> listOperations = redisTemplate.opsForList();

        logger.debug("获取习题的所有知识点ID集合");
        return listOperations.range(KeyUtils.generateKey(EXERCISE_KP, exerciseId), 0, -1);
    }

    /**
     * 获取习题的前n个知识点ID
     * @param exerciseId 习题ID
     * @param limit 个数限制
     * @return List
     *
     * @author cx
     * @since 2015-02-04
     */
    public List<Long> getKpIds(final long exerciseId, final int limit) {
        //获取List操作
        ListOperations<String, Long> listOperations = redisTemplate.opsForList();

        return listOperations.range(KeyUtils.generateKey(EXERCISE_KP, exerciseId), 0, limit);
    }

    /**
     * 获取习题资源包含的知识点编号集合
     * @param exerciseIds
     * @return List
     *
     * @author fanruiping
     * @since 2015-05-06
     */
    public Set<Long> getKpIdsByExerciseIds(List<Long> exerciseIds){
        //获取List操作
        ListOperations<String, Long> listOperations = redisTemplate.opsForList();

        Set<Long> exerciseKpIds = new HashSet<>();

        logger.debug("循环获取习题包含的知识点编号");
        //循环获取知识点编号集合
        for(Long exerciseId : exerciseIds){
            exerciseKpIds.addAll(listOperations.range(KeyUtils.generateKey(EXERCISE_KP, exerciseId), 0, -1));
        }

        return exerciseKpIds;
    }
}
